package com.moon.icoresso.Service.impl;

import com.moon.icoresso.Exception.OauthException;
import com.moon.icoresso.Service.OauthRedisService;
import com.moon.icoresso.Service.OauthService;
import com.moon.icoresso.common.utils.RandomUtil;
import com.moon.icoresso.common.utils.StringRedisService;
import com.moon.icoresso.common.utils.StringUtil;
import com.moon.icoresso.pojo.bo.OauthAccessTokenToRedisBO;
import com.moon.icoresso.pojo.bo.OauthToRedisBO;
import com.moon.icoresso.pojo.dto.OauthTokenDTO;
import com.moon.icoresso.pojo.dto.OauthTokenParam;
import com.moon.icoresso.pojo.dto.OauthTokenVerifyParam;
import com.moon.icoresso.pojo.dto.UserDTO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.moon.icoresso.pojo.constants.Constants4Oauth.*;

/**
 * @ClassName OauthServiceImpl
 * @Description
 * @Author menbbo
 * @Date 2021/2/12 17:42
 * @Version V1.0
 **/

@Service
public class OauthServiceImpl implements OauthService {
    Map<String,String> map = new ConcurrentHashMap<>();
    @Autowired
    public OauthServiceImpl(){
        map.put(OAUTH_CODE_GRANT_TYPE,OAUTH_CODE_GRANT_TYPE);
        map.put(OAUTH_PASSWORD_GRANT_TYPE,OAUTH_PASSWORD_GRANT_TYPE);
        map.put(OAUTH_CLIENT_GRANT_TYPE,OAUTH_CLIENT_GRANT_TYPE);
        map.put(OAUTH_REFRESH_GRANT_TYPE,OAUTH_REFRESH_GRANT_TYPE);
    }

    @Autowired
    private OauthRedisService oauthRedisService;
    @Autowired
    private StringRedisService<String,OauthAccessTokenToRedisBO> userDTORedisService;
    @Override
    public OauthToRedisBO checkClientIdAndRedirectUri(UserDTO userDTO) {
        OauthToRedisBO oauthToRedisBO = checkClient(userDTO);
        if(oauthToRedisBO==null||StringUtils.isEmpty(oauthToRedisBO.getClientId())){
            throw new OauthException("没有匹配到clientId");
        }
        if(StringUtils.isEmpty(userDTO.getRedirectUri())){
            throw new OauthException("redirectUri不能为空");
        }
        if(!userDTO.getRedirectUri().matches(oauthToRedisBO.getRedirectUri())){
            throw new OauthException("redirectUri不匹配该clientId");
        }
        return oauthToRedisBO;
    }
    private OauthToRedisBO checkClient(UserDTO userDTO){
        if(StringUtils.isEmpty(userDTO.getClientId())){
            throw new OauthException("clientId不能为空");
        }
        String reg = "^[A-Za-z0-9_]+$";
        if(!userDTO.getClientId().matches(reg)){
            throw new OauthException("clientId不满足格式");
        }
        OauthToRedisBO oauthToRedisBO = oauthRedisService.getClientId(CLIENT_ID_PREFIX+userDTO.getClientId());
        return oauthToRedisBO;
    }
    @Override
    public void checkUserAgent(String userAgent) {
        if(StringUtils.isEmpty(userAgent)){
            throw new OauthException("userAgent不能为空");
        }
    }

    @Override
    public void checkUserDTO(UserDTO userDTO) {
        if(StringUtils.isEmpty(userDTO.getUsername())){
            throw new OauthException("用户名不能为空");
        }
   /*     if(StringUtils.isEmpty(userDTO.getUserId())){
            throw new OauthException("用户id不能为空");
        }*/
        if(StringUtils.isEmpty(userDTO.getPassword())){
            throw new OauthException("密码不能为空");
        }
        //校验用户名与密码
    }

    @Override
    public String generateCode() {
        return OAUTH_CODE_PREFIX + RandomUtil.randomAlphabetic(32);
    }

    @Override
    public OauthTokenDTO generateToken(boolean isGenerateRefreshToken) {
        OauthTokenDTO oauthTokenDTO = new OauthTokenDTO();
        String accessToken = OAUTH_ACCESS_TOKEN_PREFIX + RandomUtil.randomAlphabetic(32);
        oauthTokenDTO.setAccessToken(accessToken);
        if(isGenerateRefreshToken){
            String refershToken = OAUTH_REFERSH_TOKEN_PREFIX + RandomUtil.randomAlphabetic(32);
            oauthTokenDTO.setRefreshToken(refershToken);
        }
        oauthTokenDTO.setExpiresIn(TOKEN_MAX_EXPIRE_TIME);
        return oauthTokenDTO;
    }

    @Override
    public void checkGrantType(String grantType) {
        if(StringUtils.isEmpty(grantType)){
            throw new OauthException("grantType为空");
        }
        if(StringUtils.isEmpty(map.get(grantType))){
            throw new OauthException("grantType不匹配");
        }
    }

    @Override
    public OauthAccessTokenToRedisBO checkRequestParam(HttpServletRequest request) {
        //从头部获取token
        String authorizationHeader = request.getHeader(HEADER_AUTHORIZATION);
        //从body获取token
        String authorizationParam = request.getParameter(PARAM_ACCESSTOKEN);

        if(StringUtils.isEmpty(authorizationHeader)&&StringUtils.isEmpty(authorizationParam)){
            throw new OauthException("token为空");
        }
        //从head中获取token的优先级高于body
        String accessToken;
        if(StringUtils.isNotEmpty(authorizationHeader)){
            if(StringUtils.containsIgnoreCase(authorizationHeader,PREFIX_UPPER_USERINFO)){
                String replaceHeader = StringUtils.replace(authorizationHeader,PREFIX_UPPER_USERINFO,PREFIX_LOWER_USERINFO);
                accessToken = StringUtils.substringAfter(replaceHeader,PREFIX_LOWER_USERINFO);
            }else {
                accessToken = authorizationHeader;
            }
        }else {
            accessToken = authorizationParam;
        }

        if(!StringUtils.containsIgnoreCase(accessToken,OAUTH_ACCESS_TOKEN_PREFIX)){
            throw new OauthException("token格式不正确");
        }
        OauthAccessTokenToRedisBO oauthAccessTokenToRedisBO = userDTORedisService.get(accessToken);

        if(oauthAccessTokenToRedisBO==null){
            throw new OauthException("该token已经失效");
        }
        return oauthAccessTokenToRedisBO;
    }

    @Override
    public void checkOauthTokenVerifyParam(OauthTokenVerifyParam oauthTokenDTO){
        if(oauthTokenDTO==null){
            throw new OauthException("oauthTokenDTO为空");
        }
        if(oauthTokenDTO.getToken()==null){
            throw new OauthException("token不能为空");
        }
        if(oauthTokenDTO.getToken()==null){
            throw new OauthException("token类型不能为空");
        }
    }

    @Override
    public void checkClientAndClientSecret(String clientId, String clientSecret) {
        UserDTO userDTO = new UserDTO();
        userDTO.setClientId(clientId);
        OauthToRedisBO oauthToRedisBO = checkClient(userDTO);
        if(oauthToRedisBO==null&&StringUtils.isEmpty(oauthToRedisBO.getClientSecret())){
            throw new OauthException("clientId与clientSecret不存在");
        }
        if(!StringUtils.equals(oauthToRedisBO.getClientSecret(),clientSecret)){
            throw new OauthException("clientId与clientSecret不匹配");
        }
    }

    @Override
    public void checkRefreshToken(OauthTokenParam oauthTokenParam) {
        if(StringUtils.isEmpty(oauthTokenParam.getGrantType())){
            throw new OauthException("grantType为空");
        }
        if(StringUtils.isEmpty(oauthTokenParam.getRefreshToken())){
            throw new OauthException("refreshToken为空");
        }
        if(StringUtils.isEmpty(oauthTokenParam.getClientId())){
            throw new OauthException("clientId为空");
        }
        if(StringUtils.isEmpty(oauthTokenParam.getClientSecret())){
            throw new OauthException("clientSecret为空");
        }
        if(!StringUtils.containsIgnoreCase(oauthTokenParam.getRefreshToken(),OAUTH_REFERSH_TOKEN_PREFIX)){
            throw new OauthException("refreshToken格式不正确");
        }
    }
}